package GUI;

import giny.model.Node;
import giny.view.NodeView;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.JScrollPane;
import javax.swing.JButton;

import General.MembershipMatrix;
import cytoscape.CyEdge;
import cytoscape.CyNetwork;
import cytoscape.CyNode;
import cytoscape.Cytoscape;
import cytoscape.data.CyAttributes;
import cytoscape.data.Semantics;
import cytoscape.ding.DingNetworkView;
import cytoscape.layout.algorithms.GridNodeLayout;
import cytoscape.view.CyNetworkView;

import javax.swing.JLabel;
import javax.swing.ScrollPaneConstants;
import javax.swing.JSlider;
import javax.swing.JPanel;
import java.awt.Font;
import javax.swing.border.BevelBorder;
import javax.swing.JList;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.JComboBox;
import javax.swing.DefaultComboBoxModel;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class ResultsWindow extends JDialog {
	private JTable table;
	DingNetworkView net;
	CyNetwork cnet;
	
	static Color[] colorTable = {null, Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE,new Color(1.0f, 0.0f, 1.0f)};
	int clusterColor[];
	double limit;
	int selectedRow;
	//results:
	MembershipMatrix u;
	int n,c;
	ArrayList<Node> nodeArray;
	CyNetwork originalNetwork;
	CyNetworkView originalNetworkView;
	int numNodes[];
	int numEdges[];
	private JLabel lblLimit;
	private JPanel clusterInfoPanel;
	private JTable nodeTable;
	private JSlider slider;
	private JLabel lblClusterNumber;
	private JLabel lblNodesInCluster;
	private JLabel lblEdgesInCluster;
	private JComboBox comboBox;
	private JLabel colorBox;
	
	
	
	public ResultsWindow(MembershipMatrix u, ArrayList<Node> array, CyNetwork network, CyNetworkView netView) {
		
		CyAttributes nodeAtts = Cytoscape.getNodeAttributes();
		originalNetwork=network;
		originalNetworkView=netView;
		setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		setPreferredSize(new Dimension(770, 500));
		setMinimumSize(new Dimension(770, 500));
		setMaximumSize(new Dimension(770, 500));
		setTitle("Extended Fuzzy Clustering Plugin Results");
		this.u=u;
		c=u.getNumberOfClusters();
		nodeArray=array;
		for(int i=0; i<nodeArray.size(); i++)
		nodeAtts.setAttribute(nodeArray.get(i).getIdentifier(),"node.fillColor","127,127,127");  
		originalNetworkView.redrawGraph(false, false);
	
		numNodes = new int[c];
		numEdges = new int[c];
		clusterColor = new int[c];
		n=nodeArray.size();
		limit=1.0/c;
		getContentPane().setLayout(null);
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		scrollPane.setBounds(10, 26, 410, 321);
		getContentPane().add(scrollPane);
		lblLimit = new JLabel("%");
		lblLimit.setBounds(380, 358, 40, 14);
		getContentPane().add(lblLimit);
		table = new JTable();

		
		table.setRowHeight(150);
		scrollPane.setViewportView(table);
		table.setModel(new DefaultTableModel(
			new Object[][] {
			},
			new String[] {
				"Number", "Cluster Image", "Cluster Data"
			}
		) {
			Class[] columnTypes = new Class[] {
				Integer.class, ImageIcon.class, Object.class
			};
			public Class getColumnClass(int columnIndex) {
			
				return columnTypes[columnIndex];
			}
			public boolean isCellEditable(int row, int column)
			{
				return false;
			
			}
		});
		table.getColumnModel().getColumn(0).setPreferredWidth(50);
		table.getColumnModel().getColumn(0).setMinWidth(50);
		table.getColumnModel().getColumn(0).setMaxWidth(50);
		table.getColumnModel().getColumn(1).setPreferredWidth(150);
		table.getColumnModel().getColumn(1).setMinWidth(150);
		table.getColumnModel().getColumn(1).setMaxWidth(150);
		table.getColumnModel().getColumn(2).setPreferredWidth(115);
		table.getColumnModel().getColumn(2).setMinWidth(100);
		
		JButton btnExport = new JButton("Export");
		btnExport.setBounds(77, 429, 89, 23);
		getContentPane().add(btnExport);
		
		JButton btnClose = new JButton("Close");
		btnClose.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				closePressed();
			}
		});
		btnClose.setBounds(224, 429, 89, 23);
		getContentPane().add(btnClose);
		
		slider = new JSlider();
		slider.addPropertyChangeListener(new PropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent arg0) {
				//limit=slider.getValue()/1000.0;
				lblLimit.setText(slider.getValue()/10+"."+slider.getValue()%10+"%");
			}
		});
		slider.setValue(333);
		slider.setMaximum(1000);
		slider.setBounds(139, 358, 235, 23);
		getContentPane().add(slider);
		
		JLabel lblClusterAssociationLimit = new JLabel("Cluster association limit:");
		lblClusterAssociationLimit.setBounds(10, 358, 135, 14);
		getContentPane().add(lblClusterAssociationLimit);
		
	
		
		JLabel lblAverageClustersPer = new JLabel("Average clusters per node:");
		lblAverageClustersPer.setBounds(10, 393, 156, 14);
		getContentPane().add(lblAverageClustersPer);
		
		JLabel lblNodesPerCluster = new JLabel("???");
		lblNodesPerCluster.setBounds(171, 393, 113, 14);
		getContentPane().add(lblNodesPerCluster);
		
		clusterInfoPanel = new JPanel();
		clusterInfoPanel.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
		clusterInfoPanel.setBounds(430, 26, 299, 426);
		getContentPane().add(clusterInfoPanel);
		clusterInfoPanel.setLayout(null);
		
		JButton btnNewButton = new JButton("Create network from this cluster");
		btnNewButton.setBounds(10, 392, 279, 23);
		clusterInfoPanel.add(btnNewButton);
		
		lblClusterNumber = new JLabel("Cluster Number: ");
		lblClusterNumber.setFont(new Font("Verdana", Font.BOLD, 13));
		lblClusterNumber.setBounds(10, 11, 188, 23);
		clusterInfoPanel.add(lblClusterNumber);
		
		lblNodesInCluster = new JLabel("Nodes in cluster: ");
		lblNodesInCluster.setBounds(30, 45, 120, 14);
		clusterInfoPanel.add(lblNodesInCluster);
		
		lblEdgesInCluster = new JLabel("Edges in cluster: ");
		lblEdgesInCluster.setBounds(30, 70, 120, 14);
		clusterInfoPanel.add(lblEdgesInCluster);
		
		JLabel lblListOfNodes = new JLabel("List of nodes:");
		lblListOfNodes.setBounds(30, 95, 120, 14);
		clusterInfoPanel.add(lblListOfNodes);
		
		JPanel panel_1 = new JPanel();
		panel_1.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
		panel_1.setBounds(10, 304, 279, 71);
		clusterInfoPanel.add(panel_1);
		panel_1.setLayout(null);
		
		JLabel lblColorNodesIn = new JLabel("Color nodes in this cluster with: ");
		lblColorNodesIn.setBounds(10, 11, 168, 14);
		panel_1.add(lblColorNodesIn);
		
		JButton btnApply = new JButton("Apply");
		btnApply.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				applyColor();
			}
		});
	
		comboBox = new JComboBox();
		comboBox.setModel(new DefaultComboBoxModel(new String[] {"NONE", "Red", "Yellow", "Green", "Blue", "Purple"}));
		comboBox.setSelectedIndex(0);
		comboBox.setBounds(199, 8, 70, 20);
		panel_1.add(comboBox);
	
		btnApply.setBounds(89, 36, 89, 23);
		panel_1.add(btnApply);
		
		
		
		colorBox = new JLabel("    ");
		colorBox.setOpaque(true);
		colorBox.setBounds(228, 11, 61, 61);
		clusterInfoPanel.add(colorBox);
		
		JScrollPane scrollPane_1 = new JScrollPane();
		scrollPane_1.setBounds(40, 120, 240, 161);
		clusterInfoPanel.add(scrollPane_1);
		
		slider.setValue((int)(limit*1000));
		lblLimit.setText(slider.getValue()/10+"."+slider.getValue()%10+"%");
		
		nodeTable = new JTable();
		nodeTable.setModel(new DefaultTableModel(
			new Object[][] {
				{null, null},
				{null, null},
			},
			new String[] {
				"Node", "Association"
			}
		) {
			Class[] columnTypes = new Class[] {
				String.class, String.class
			};
			public Class getColumnClass(int columnIndex) {
				return columnTypes[columnIndex];
			}
			public boolean isCellEditable(int row, int column)
			{
				return false;
			}
		});
		nodeTable.getColumnModel().getColumn(1).setPreferredWidth(70);
		nodeTable.getColumnModel().getColumn(1).setMinWidth(50);
		nodeTable.getColumnModel().getColumn(1).setMaxWidth(70);
		scrollPane_1.setViewportView(nodeTable);
		limit=1.0/u.getNumberOfClusters();
		//cnet=Cytoscape.createNetwork("network1", false); 
		 DefaultTableModel m=(DefaultTableModel)table.getModel();
		for (int k=0; k<u.getNumberOfClusters();k++)
		{
			int nodes=0, edges=0;
			ArrayList<Node> clusterNodes= new ArrayList<Node>();
			cnet=Cytoscape.createNetwork("network1", false); 
			for (int i=0; i<n; i++)
			{
				if (u.get(i, k)>=limit)
				{
					nodes++;
					cnet.addNode(nodeArray.get(i));
					clusterNodes.add(nodeArray.get(i));
				}
				numNodes[k]=nodes;
			}
			
			for (int i=0; i<clusterNodes.size(); i++)
				for (int j=0; j<i; j++)
				{
					if (originalNetwork.isNeighbor(clusterNodes.get(i), clusterNodes.get(j)))
					{
						 CyEdge edge = Cytoscape.getCyEdge(clusterNodes.get(i), clusterNodes.get(j), Semantics.INTERACTION, "pp", true);
						 cnet.addEdge(edge);
						 edges++;
					}
				}
			numEdges[k]=edges;
				net=new DingNetworkView(cnet,"net1");
				  GridNodeLayout l = new GridNodeLayout();
				  l.doLayout(net);
				  net.setBackgroundPaint(Color.WHITE);
				  Object[] arr = new Object[3];
				  arr[1] = new ImageIcon(net.createImage(150, 150, 0.75));
				  arr[0]=k+1;
				  arr[2]="Nodes: "+ nodes+ "  \nEdges: "+ edges;
				  m.addRow( arr);
				  Cytoscape.destroyNetwork(cnet);
			
			
		}
		
		double sum=0;
		for (int i=0; i<c; i++)
		{
			sum+=numNodes[i];
		}
		lblNodesPerCluster.setText(sum/n+"");
		selectedRow=table.getSelectedRow();
		updateClusterInfo();
		
		
		 table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			
			@Override
			public void valueChanged(ListSelectionEvent arg0) {
				if (table.getSelectedRow()!=selectedRow)
				{
					selectedRow=table.getSelectedRow();
					updateClusterInfo();
				}
				
				
			}
		});
		
		
		   /* 
		    
		    
		    
		    CyNode node0 = Cytoscape.getCyNode("rain", true);
		    CyNode node1 = Cytoscape.getCyNode("rainbow", true);
		    CyNode node2 = Cytoscape.getCyNode("rabbit", true);
		    CyNode node3 = Cytoscape.getCyNode("yellow", true);
		   
		   cnet.addNode(node0);
		   cnet.addNode(node1);
		   cnet.addNode(node2);
		   cnet.addNode(node3);
		   
		   CyEdge edge0 = Cytoscape.getCyEdge(node0, node1, Semantics.INTERACTION, "pp", true);
		   CyEdge edge1 = Cytoscape.getCyEdge(node0, node2, Semantics.INTERACTION, "pp", true);
		   CyEdge edge2 = Cytoscape.getCyEdge(node0, node3, Semantics.INTERACTION, "pp", true);
		   
		   cnet.addEdge(edge0);
		   cnet.addEdge(edge1);
		   cnet.addEdge(edge2);
		net=new DingNetworkView(cnet,"net1");*/
		
		setVisible(true);
		
	}
	
	public void updateClusterInfo()
	{
		if (selectedRow==-1)
		{
			clusterInfoPanel.setVisible(false);
			return;
		}
		
		lblClusterNumber.setText("Cluster Number: "+ (selectedRow+1));
		lblNodesInCluster.setText("Nodes in cluster: " + numNodes[selectedRow]);
		lblEdgesInCluster.setText("Edges in cluster: " + numEdges[selectedRow]);
		
		int x=clusterColor[selectedRow];
		
		if (x!=0)
			colorBox.setBackground(colorTable[x]);
		else
			colorBox.setBackground(clusterInfoPanel.getBackground());
			
		comboBox.setSelectedIndex(x);
		DefaultTableModel m = (DefaultTableModel)nodeTable.getModel();
		
		while(m.getRowCount()>0)   // clear the table
			m.removeRow(0);
		
		for(int i=0; i<n; i++)
		{
			if (u.get(i, selectedRow)>=limit)
			{
				Object a[]=new Object[2];
				a[0]=nodeArray.get(i).getIdentifier();
				a[1]=(((int)(u.get(i, selectedRow)*1000))/10.0)+"%";
				m.addRow(a);
			}
		}
		
		
		clusterInfoPanel.setVisible(true);
		
	}
	
	private void applyColor()
	{
		
		int x=comboBox.getSelectedIndex();
		// update the gui:
		clusterColor[selectedRow]=x;
		
		if (x!=0)
			colorBox.setBackground(colorTable[x]);
		else
			colorBox.setBackground(clusterInfoPanel.getBackground());
			
		// update the CyNetworkView:
		
		
		CyAttributes nodeAtts = Cytoscape.getNodeAttributes();
		
		for (int i=0; i<n; i++)
		{
			Color color=colorMixer(i);
		//	NodeView nv = originalNetworkView.getNodeView(nodeArray.get(i));
		//	nv.setUnselectedPaint(color);
		//	originalNetworkView.setNodeObjectProperty(nodeArray.get(i).getRootGraphIndex(), originalNetworkView.NODE_PAINT, color);
			nodeAtts.setAttribute(nodeArray.get(i).getIdentifier(),"node.fillColor",color.getRed()+","+color.getGreen()+","+color.getBlue());  
			
			
		}
		
	originalNetworkView.redrawGraph(false, false);
		//originalNetworkView.updateView();
		
	}
	
	
	private Color colorMixer(int nodeIndex)
	{
		double red=0, green=0, blue=0;

		for (int k=0; k<c; k++)
		{
			if (clusterColor[k]!=0)
			{
				red+=colorTable[clusterColor[k]].getRed()*u.get(nodeIndex, k);
				green+=colorTable[clusterColor[k]].getGreen()*u.get(nodeIndex, k);
				blue+=colorTable[clusterColor[k]].getBlue()*u.get(nodeIndex, k);
			}
			else
			{
				red+=Color.GRAY.getRed()*u.get(nodeIndex, k);
				green+=Color.GRAY.getGreen()*u.get(nodeIndex, k);
				blue+=Color.GRAY.getBlue()*u.get(nodeIndex, k);
			}
		}
		
		return new Color((int)red, (int)green, (int)blue);
	}
	
	private void closePressed()
	{
		this.dispose();
	}
	
	
	public static void main(String args[])
	{
		//JOptionPane.showMessageDialog(null, "THIS IS WORKING!");
		//ResultsWindow rs= new ResultsWindow(null, null, null);
	//	rs.setVisible(true);
		
	}
}


